package com.scse.bms.web.client;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.scse.bms.domain.*;
import com.scse.bms.entity.HeadImgDO;
import com.scse.bms.entity.UserDO;
import com.scse.bms.entity.UserHeadImgDO;
import com.scse.bms.service.HeadImgService;
import com.scse.bms.service.ThemeService;
import com.scse.bms.service.UserService;
import com.scse.bms.service.UserRoleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

/**
 * @Title: UserController
 * @Author: 吴赠禹
 * @Date: 2020/10/30 0030
 * @Version: 1.0
 * @Description: 用户控制器
 */

@Slf4j
@Controller
public class UserController {

    @Autowired
    @Qualifier("userService")
    private UserService userService;

    @Autowired
    @Qualifier("userRoleService")
    private UserRoleService userRoleService;

    @Autowired
    private ThemeService themeService;


    @Autowired
    private HeadImgService headImgService;

    /**
     * 引入描述信息属性文件
     */
    private final Properties desProp = new Properties();


    @GetMapping("/user/self")
    public String toSelfPage(Model model) {
        log.info("[toSelfPage] 用户请求进入个人中心");
        List<MenuItem> itemlist = themeService.getTheme();
        model.addAttribute("itemList", itemlist);
        return "self";
    }


    /**
     * 用户注册处理
     * @param user
     * @param request
     * @return
     * @throws IOException
     */
    @PostMapping("/user/register")
    @ResponseBody
    public String addUser(@RequestBody User user, HttpServletRequest request) throws IOException {
        Resource resource = new ClassPathResource("description.properties");
        desProp.load(new FileInputStream(resource.getFile()));
        log.info(this.getClass() + " " + user);
        // 验证码校验
        String code = user.getRandomCode();
        HttpSession session = request.getSession();
        String value = (String) session.getAttribute("code");
        if (!code.equals(value)) {
            return String.valueOf(1003);
        }
        int ret = userService.addUser(user.getUserDO());
        log.warn(this.getClass() + " [addUser] ret：" + ret);
        // 手机号码被注册
        if (ret == 1002) {
            return String.valueOf(1002);
        }
        // 用户名被注册
        if (ret == 1001) {
            return String.valueOf(1001);
        }
        if (ret > 0) {
            // 添加用户成功，mybatis自动注入用户id，为用户设置权限记录
            int authFlag = userRoleService.addAuthBe2(user.getUserDO().getId());
            if (authFlag > 0) {
                log.info(String.format("成功为用户 {%s} 设置了普通权限。", user.getUserDO().getUsername()));
            } else {
                log.warn(String.format("用户 {%s} 未能设置权限。", user.getUserDO().getUsername()));
            }
            return String.valueOf(200);
        } else {
            return String.valueOf(500);
        }
    }


    /**
     * 分页查询所有用户
     * @param page
     * @param limit
     * @return
     */
    @GetMapping("/user/all")
    @ResponseBody
    public String getAllUser(@RequestParam(required = false, defaultValue = "1") Integer page,
                             @RequestParam(required = false, defaultValue = "15") Integer limit) {
        log.info("[getAllUser] 请求获取用户列表。 page：{} limit：{}", page, limit);
        // 获取记录总数（必需，用于前端分页，否则仅显示1页）
        int count = userService.selectAllUserCount();
        // 移动记录指针（数据下标从0开始）
        int pageIndex = (page - 1) * limit;
        List<UserVO> users = userService.selectAllUser(pageIndex, limit);
        // 返回符合layUI数据表格解析的格式
        JSONObject json = new JSONObject();
        // code必须为0，否则导致渲染失败（也可以自定义）
        json.put("code", 0);
        json.put("msg", "查询成功");
        json.put("count", count);
        json.put("data", users);
        return json.toString();
    }


    /**
     * 带条件的分页查询所有用户
     * @param user
     * @return
     */
    @PostMapping("/user/all")
    @ResponseBody
    public String getAllUserByCase(@RequestBody UserCaseVO user) {
        log.info("[getAllUserByCase] 条件查询分页：{}", user);
        int page = user.getPage();
        int limit = user.getLimit();
        // 获取符合条件的用户总数
        int count = userService.statAllUserByCase(user);
        int pageIndex = (page - 1) * limit;
        // TODO 需要增加limit关键字
        List<UserVO> users = userService.selectAllUserByCase(user, pageIndex, limit);
        // 返回符合layUI数据表格解析的格式
        JSONObject json = new JSONObject();
        // code必须为0，否则导致渲染失败（也可以自定义）
        json.put("code", 0);
        json.put("msg", "查询成功");
        json.put("count", count);
        json.put("data", users);
        return json.toString();
    }


    /**
     * 随机获取10个头像给用户选择
     * 注意保存的是VO对象，但给用户选择只需要img id、src属性，因此使用DO对象
     * @return
     */
    @GetMapping("/user/getProfile")
    @ResponseBody
    public String getProfile(HttpSession session) {
        log.info("[getProfile] 用户请求修改头像，从数据库获取头像列表供用户选择。");
        // 注意新注册用户是没有头像的，需要判空
        UserHeadImgVO headImg = (UserHeadImgVO) session.getAttribute("headImg");
        String originalProfile = "";
        if (headImg != null) {
            originalProfile = headImg.getSrc();
        }
        // 选择10条头像，排除用户自己的头像
        List<HeadImgDO> list = headImgService.selectHeadImgForUserChose(originalProfile);
        // 集合类型，使用JSONArray解析
        log.info("[getProfile] 返回的头像列表：" + JSON.toJSONString(list));
        return JSON.toJSONString(list);
    }


    /**
     * 用户请求修改头像
     * TODO 注意事项，由于之前的设计是将头像放入session中，因此修改后需要重新保存session
     * @param userHeadImgDO
     * @return
     */
    @PostMapping("/user/updateProfile")
    @ResponseBody
    public String updateProfile(@RequestBody UserHeadImgDO userHeadImgDO, HttpSession session) {
        log.info("[updateProfile] 用户请求修改头像：" + userHeadImgDO);
        // 1、查询用户是否有头像，有则修改，无则添加
        Integer exits = headImgService.selectUserIfExistProfile(userHeadImgDO.getUserId());
        int result;
        // 2、如果返回结果非空，则存在。存在则修改
        if (exits != null) {
            result = headImgService.updateUserProfile(userHeadImgDO);
        } else {
            result = headImgService.addUserProfile(userHeadImgDO);
        }
        // 刷新用户信息。重写user session（因为src保存在UserVO中）
        UserVO user = userService.getUserFullInfoById(userHeadImgDO.getUserId());
        session.setAttribute("loginUser", user);
        log.info("[updateProfile] 执行完毕，重新放入session的数据：" + user);
        // 返回受影响行数（非0表示成功）
        return String.valueOf(result);
    }


    /**
     * 暂时使用Use人DO接受参数
     * @param userDO
     * @return
     */
    @PostMapping("/user/updateUserName")
    @ResponseBody
    public String updateUserName(@RequestBody UserDO userDO, HttpSession session) {
        log.info("[updateUserName] 用户请求修改用户名：" + userDO);
        // 先查询用户名是否存在
        Integer flag = userService.selectUserNameIfExistById(userDO.getUsername());
        // 为空表示可以使用该昵称
        if (flag == null) {
            // 此处表示受影响的行数
            flag = userService.updateUserName(userDO);
            // 刷新会话
            UserVO user = userService.getUserFullInfoById(userDO.getId());
            session.setAttribute("loginUser", user);
        } else {
            // -1表示已被使用
            flag = -1;
        }
        return String.valueOf(flag);
    }


    /**
     * 用户更新个人邮箱
     * @param userDO
     * @param session
     * @return
     */
    @PostMapping("/user/updateEmail")
    @ResponseBody
    public String updateEmail(@RequestBody UserDO userDO, HttpSession session) {
        log.info("[updateEmail] 用户请求更新邮箱：" + userDO);
        // 先查询邮箱是否被使用
        Integer flag = userService.selectEmailIfExistById(userDO.getEmail());
        if (flag == null) {
            // 修改用户邮箱
            flag = userService.updateEmail(userDO);
            // 刷新会话
            UserVO user = userService.getUserFullInfoById(userDO.getId());
            session.setAttribute("loginUser", user);
            log.info("[updateEmail] 用户更新邮件完成，重绘session：" + user);
        } else {
            // -1表示被使用
            flag = -1;
        }
        return String.valueOf(flag);
    }


    /**
     * 核实密码是否一致
     * @param userDO
     * @return
     */
    @PostMapping("/user/verifyPassword")
    @ResponseBody
    public String verifyPassword(@RequestBody UserDO userDO) {
        log.info("[verifyPassword] 用户请求验证原密码：" + userDO);
        // 先验证用户名密码是否正确
        // 先对前端传送的密码进行md5()加密与数据库算法一致
        String encryption = DigestUtil.md5Hex(userDO.getPassword());
        userDO.setPassword(encryption);
        Integer flag = userService.selectPasswordIfCorrect(userDO);
        if (flag != null) {
            flag = 1;
        } else {
            flag = 0;
        }
        log.info("[verifyPassword] flag值：" + flag);
        return String.valueOf(flag);
    }


    /**
     * 修改用户密码
     * @param userDO
     * @return
     */
    @PostMapping("/user/updatePassword")
    @ResponseBody
    public String updatePassword(@RequestBody UserDO userDO) {
        log.info("[updatePassword] 用户请求修改密码：" + userDO);
        // 修改密码，先加密
        String encryption = DigestUtil.md5Hex(userDO.getPassword());
        userDO.setPassword(encryption);
        Integer flag = userService.updatePassword(userDO);
        log.info("[updatePassword] flag值：" + flag);
        return String.valueOf(flag);
    }





    /**
     * 测试接口服务器异常5xx
     * @return
     */
    @GetMapping("/test/error")
    public String error() {
        int i = 10 / 0;
        return "error";
    }


}

